# import jusmargui
from PySide2.QtWidgets import (
    QApplication,
    QWidget,
    QTableWidgetItem,
    QTableWidget,
    QHeaderView,
    QAbstractItemView,
    QVBoxLayout,
    QTabWidget,
    QGroupBox,
    QLabel,
    QLineEdit,
    QHBoxLayout,
    QGridLayout,
    QComboBox,
    QPushButton,
    QListWidget,
    QDialog,
    QButtonGroup,
    QRadioButton,
    QCheckBox,
    QListWidgetItem,
    QMessageBox,
    QGraphicsColorizeEffect,
    QFileDialog,
    QAbstractItemView,
)
from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QPixmap, QDoubleValidator, QIntValidator, QImage
import sys
import csv
import os
import json
import subprocess
import copy
import ast
from gui.controls import envs
from datetime import datetime
from .. import message_box as MBox
from .. import config as Config
from ..utils import Utils
from ..dlg_model_params import DlgModelMutliParams
from ..params_table import ParamsTable, CustomTableWidgetItem
from .stringed_bar_size import StringedBarSize
from .stringed_bar_edit import DlgStringedBarEdit


class stringBarTable(ParamsTable):
    action_signal = Signal(str, int, list)

    def __init__(self, rows=0, columns=2, isLibrary=False, parent=None):
        super(stringBarTable, self).__init__(rows, columns, isLibrary, parent)
        self.ED = self.contextMenu.addAction("编辑")
        self.ED.triggered.connect(self.editCell)
        self.rowNoEdit = []

    def add(self):
        lastRow = self.selectedLastRow()
        if lastRow < 0:
            lastRow = self.rowCount()
        else:
            lastRow = lastRow + 1
        self.action_signal.emit("add", lastRow, [])

    def editCell(self):
        row = self.selectedLastRow()
        if row < 0:
            MBox.warning("请选择要编辑的行")
            return
        rowData = self.getRowData(row)
        size = rowData[2]
        if size:
            rowData[2] = size.split(",")
        self.action_signal.emit("edit", row, rowData)

    def rowSetNoEdit(self, toNoEdit):
        if isinstance(toNoEdit, list):
            self.rowNoEdit = toNoEdit
        else:
            self.rowNoEdit.append(toNoEdit)

    def validate_table_data(self, typeMap):
        dict = {}
        keyCol = 0 if self.uniqueFlagColumn == -1 else self.uniqueFlagColumn
        for row in range(self.rowCount()):
            rowData = self.getRowDataCheck(row)
            if not rowData:
                return False
            else:
                # # 判断是否为空，空返回int
                # if rowData[keyCol] == "" or rowData[keyCol] is None:
                #     return row + 1
                # 判断是否重复，重复返回str
                if str(rowData[keyCol]) in dict:
                    return str(row + 1)
                # 判断类型和尺寸是否有格式错误，是否匹配
                if rowData[1] not in typeMap:
                    return row + 1
                # 获取期望尺寸数量
                expectedSizeLen = typeMap.get(rowData[1])
                sizeLen = 0
                try:
                    # 获取实际尺寸数量
                    sizeLen = [float(item.strip()) for item in rowData[2].split(",")]
                except:
                    return row + 1
                if len(sizeLen) != expectedSizeLen:
                    return row + 1

                dict[str(rowData[keyCol])] = rowData
        return dict

    # 插入一行，可设置数据
    def addRow(self, row=-1, rowData=[], isAddIncrementing=False, isPastOrImport=False):
        row_position = row
        if row < 0:
            row_position = self.rowCount()
        self.insertRow(row_position)
        for column in range(self.columnCount()):
            item = CustomTableWidgetItem("")
            if column in self.rowDoubleClick:
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
            if rowData:
                if len(rowData) > column:
                    if item.getReadyOnly() == False:
                        item.setText(self.getRuleValueToStr(rowData[column], column))
            if column in self.rowNoEdit:
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
            if column == 1:
                item.setData(
                    Qt.UserRole, self.getRuleValueToStr(rowData[column], column)
                )  # 实际值
                item.setData(
                    Qt.DisplayRole, self.getRuleValueToStr(rowData[column], column)
                )  # 显示文本
            self.setItem(row_position, column, item)


class CGridLayout(QGridLayout):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAlignment(Qt.AlignTop)

        # # 动态设置可编辑性
        # if col == 1 and row == 0:  # 特定单元格（第二列第一行）可编辑
        #     item.setFlags(item.flags() | Qt.ItemIsEditable)
        # else:
        #     item.setFlags(item.flags() & ~Qt.ItemIsEditable)


class DlgStringedBarLibrary(DlgModelMutliParams):
    stringedBarLibrary_save_signal = Signal(object)

    def __init__(self, parent=None, data=[]):
        super().__init__(parent)
        self.setWindowTitle("桁条库")
        self.resize(600, 600)

        layout = QVBoxLayout()
        self.table = stringBarTable(rows=0, columns=3)
        self.table.verticalHeader().setVisible(True)
        # self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.table.setHorizontalHeaderLabels(
            [
                "名称",
                "类型",
                "尺寸",
            ]
        )
        self.table.rowSetSelect(
            [1],
            {
                "1": [
                    {"value": "BAR", "title": "BAR"},
                    {"value": "BOX", "title": "BOX"},
                    {"value": "BOX1", "title": "BOX1"},
                    {"value": "CHAN", "title": "CHAN"},
                    {"value": "CHAN1", "title": "CHAN1"},
                    {"value": "CHAN2", "title": "CHAN2"},
                    {"value": "CROSS", "title": "CROSS"},
                    {"value": "DBOX", "title": "DBOX"},
                    {"value": "H", "title": "H"},
                    {"value": "HAT", "title": "HAT"},
                    {"value": "HAT1", "title": "HAT1"},
                    {"value": "HEXA", "title": "HEXA"},
                    {"value": "I", "title": "I"},
                    {"value": "l1", "title": "l1"},
                    {"value": "ROD", "title": "ROD"},
                    {"value": "T", "title": "T"},
                    {"value": "T1", "title": "T1"},
                    {"value": "T2", "title": "T2"},
                    {"value": "TUBE", "title": "TUBE"},
                    {"value": "TUBE2", "title": "TUBE2"},
                    {"value": "Z", "title": "Z"},
                ],
            },
        )
        self.table.rowSetDoubleClick([2])
        # self.table.rowSetNoEdit([1, 2])
        self.table.rowSetNoEdit([2])
        self.table.select_changed_signal.connect(self.type_changed_signal)
        self.table.custom_double_clicked_signal.connect(self.on_sizeChange_clicked)
        if Config.useLibraryLocking:
            self.table.isHandleDel = True
        self.table.uniqueFlagColumn = 0
        self.table.action_signal.connect(self.on_table_action_signal)
        layout.addWidget(self.table)

        btnLayout = QHBoxLayout()
        addBtn = QPushButton("新增")
        importBtn = QPushButton("导入csv")
        clearBtn = QPushButton("清空")
        cancelBtn = QPushButton("取消")
        okBtn = QPushButton("确定")

        btnLayout.setAlignment(Qt.AlignCenter)
        btnLayout.addWidget(addBtn)
        btnLayout.addWidget(importBtn)
        btnLayout.addWidget(clearBtn)
        btnLayout.addWidget(okBtn)
        btnLayout.addWidget(cancelBtn)
        layout.addLayout(btnLayout)

        addBtn.clicked.connect(self.on_addBtn_clicked)
        importBtn.clicked.connect(self.on_importBtn_clicked)
        clearBtn.clicked.connect(self.on_clearBtn_clicked)
        okBtn.clicked.connect(self.on_okBtn_clicked)
        cancelBtn.clicked.connect(self.close)

        self.setLayout(layout)

        self.cacheFile = Config.cachePath + "stringedBarLibrary.json"
        self.loadTableData(self.cacheFile, self.table)
        if Config.useLibraryLocking:
            self.lockingData = self.handleLockingTable()
            envs.ipimas_changeLockStringedBar = (
                lambda *args, **kwargs: self.lockLibraryChange(*args, **kwargs)
            )

    def lockLibraryChange(self):
        if self.isVisible():
            self.lockingData = self.handleLockingTable()

    def handleLockingTable(self):
        lockingData = Utils.read_json(Config.stringedBarTable)
        for row in range(self.table.rowCount()):
            item = self.table.item(row, 0)
            if item and item.text() in lockingData:
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                item.setReadyOnly(True)
                self.table.hasNoEditCell = True
        return lockingData

    def on_table_action_signal(self, action, row, data):
        names = self.table.getColumnDict(curRow=row)
        if action == "add":
            dlgStringedBarEdit = DlgStringedBarEdit.show(
                parent=self, params={"row": row, "names":names}
            )
            dlgStringedBarEdit.ok_signal.connect(self.on_update_signal)

        elif action == "edit":
            dlgStringedBarEdit = DlgStringedBarEdit.show(
                parent=self, params={"type": "edit", "row": row, "names":names}
            )
            dlgStringedBarEdit.updateUI(data)
            dlgStringedBarEdit.ok_signal.connect(self.on_update_signal)

    def on_addBtn_clicked(self):
        self.table.add()

    def on_update_signal(self, type, data, row):
        if type == "add":
            self.table.addRow(rowData=data)
        elif type == "edit":
            self.table.fillRowData(row=row, rowData=data)

    def on_importBtn_clicked(self):
        filePath = Utils.ImportFile()
        if filePath:
            _, fileExtension = os.path.splitext(filePath)
            fileExtension = fileExtension.lower()
            if fileExtension == ".json":
                self.loadTableList(filePath, self.table)
            elif fileExtension == ".csv":
                self.load_csv(filePath)
                
    def on_exportBtn_clicked(self):
        Utils.export_to_csv(self.table)

    def on_okBtn_clicked(self):

        typeMap = {
            "BAR": 2,
            "BOX": 4,
            "BOX1": 6,
            "CHAN": 4,
            "CHAN1": 4,
            "CHAN2": 4,
            "CROSS": 4,
            "DBOX": 10,
            "H": 4,
            "HAT": 4,
            "HAT1": 5,
            "HEXA": 3,
            "I": 6,
            "l1": 4,
            "ROD": 1,
            "T": 4,
            "T1": 4,
            "T2": 4,
            "TUBE": 2,
            "TUBE2": 2,
            "Z": 4,
        }

        data = self.table.validate_table_data(typeMap)
        if isinstance(data, str):
            MBox.warning(f"第{data}行名称已存在!")
            return
        # 这里需要先判断完整数据再判断尺寸格式 顺序不能变
        if data == False:
            MBox.warning("表格中存在未填写的内容，请填写完整数据后再保存!")
            return
        if isinstance(data, int):
            MBox.warning(f"第{data}行中类型或尺寸格式有误，请按规范填写!")
            return
        data = Utils.sortDictCustom(data)
        Utils.write_json(self.cacheFile, data)
        if Config.useLibraryLocking:
            self.updateLockingTable(data)
        self.close()
        self.stringedBarLibrary_save_signal.emit(data)
        if hasattr(envs, "ipimas_changeStringedBar"):
            envs.ipimas_changeStringedBar(library=data)

    def updateLockingTable(self, data):
        for key, item in self.lockingData.items():
            if key in data:
                item["content"] = data[key]
        Utils.write_json(Config.stringedBarTable, self.lockingData)

    def on_sizeChange_clicked(self, value, row, col):
        names = self.table.getColumnDict(curRow=row)
        rowData = self.table.getRowData(row)
        size = rowData[2]
        if size:
            rowData[2] = size.split(",")
        dlgStringedBarEdit = DlgStringedBarEdit.show(
            parent=self,
            params={"type": "edit", "row": row, "names": names},
        )
        dlgStringedBarEdit.updateUI(rowData, True)
        dlgStringedBarEdit.ok_signal.connect(self.on_update_signal)

    def type_changed_signal(self, index, lastValue, value ):
        row = index.row()
        if value != lastValue:
            item = self.table.item(row, 2)
            if item:
                item.setText("")

    def updateSize(self, value, row, col):
        # isExistValue = self.table.isExistValueAtRow(value, col)
        # if isinstance(isExistValue, int):
        #     MBox.warning("名称")
        #     return
        self.table.updateCellData(row, col, value)

    def on_clearBtn_clicked(self):
        self.table.clearRow()

    def load_csv(self, filename):
        data = Utils.loadCsv(filename, labList=["名称", "类型", "尺寸"])
        copyCsvData = data.copy()
        tableDict = self.table.getTableDict()
        for addIndex in range(len(copyCsvData) - 1, -1, -1):  # 倒序遍历
            csvRow = copyCsvData[addIndex]
            if csvRow[0] is not None and str(csvRow[0]) in tableDict:
                self.table.updateRowData(tableDict[str(csvRow[0])]["row"], csvRow)
                del data[addIndex]
        self.table.addMulitRows(data)

    def saveTableData(self, file, table):
        data = table.getTableData()
        Utils.write_json(file, data)

    def loadTableData(self, file, table):
        data = Utils.read_json(file)
        for _, row_data in data.items():
            table.addRow(rowData=row_data)

    def loadTableList(self, file, table):
        data = Utils.read_json(file)
        for row_data in data:
            table.addRow(rowData=row_data)
# if __name__ == "__main__":
#     app = QApplication(sys.argv)
#     window = StringedBarLibraryDialog()
#     window.show()
#     sys.exit(app.exec_())
